package com.boot.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.boot.constants.StatusConstants;
import com.boot.entity.Comment;
import com.boot.entity.Question;
import com.boot.entity.QuestionAssignment;
import com.boot.entity.User;
import com.boot.exception.BusinessException;
import com.boot.mapper.CommentMapper;
import com.boot.mapper.QuestionAssignmentMapper;
import com.boot.service.ICommentService;
import com.boot.service.IQuestionService;
import com.boot.service.IUserService;
import com.boot.utils.SecurityUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class CommentServiceImpl extends ServiceImpl<CommentMapper, Comment> implements ICommentService {
    @Resource
    private IQuestionService questionService;

    @Resource
    private QuestionAssignmentMapper questionAssignmentMapper;

    @Resource
    private IUserService userService;

    @Resource(name = "stringRedisTemplate")
    private StringRedisTemplate redisTemplate;

    @Override
    public void publishComment(Long questionId, String content) {
        Long userId = SecurityUtils.requireCurrentUserId();

        // 权限校验
        if (isNotAllowedToAccessQuestion(questionId, userId)) {
            throw new BusinessException("无权在此问题下发表评论");
        }

        // 添加Redis限制：检查该用户在该问题下的待审批评论数量
        String redisKey = "comment:pending:" + userId + ":" + questionId;
        Long pendingCount = redisTemplate.opsForValue().increment(redisKey);

        if (pendingCount != null && pendingCount > 3) {
            redisTemplate.opsForValue().decrement(redisKey); // 回滚计数
            throw new BusinessException("每个用户在每个问题下最多只能有3条待审批评论");
        }

        // 设置过期时间（24小时），避免长期占用内存
        redisTemplate.expire(redisKey, 24, TimeUnit.HOURS);

        Comment comment = new Comment();
        comment.setQuestionId(questionId);
        comment.setUserId(userId);
        comment.setContent(content.trim());
        comment.setStatus(StatusConstants.CommentStatus.PENDING); // 初始待审核
        comment.setCreatedAt(LocalDateTime.now());
        comment.setUpdatedAt(LocalDateTime.now());

        boolean success = this.save(comment);
        if (!success) {
            // 保存失败时回滚Redis计数
            redisTemplate.opsForValue().decrement(redisKey);
            throw new BusinessException("评论发布失败");
        }
    }

    @Override
    public List<Comment> getApprovedCommentsByQuestionId(Long questionId) {
        Long userId = SecurityUtils.requireCurrentUserId();

        // 权限校验
        if (isNotAllowedToAccessQuestion(questionId, userId)) {
            throw new BusinessException("无权查看此问题的评论");
        }

        // 查询：所有已通过的评论 + 自己发布的非删除/禁用评论（包含待审）
        QueryWrapper<Comment> wrapper = new QueryWrapper<>();
        wrapper.eq("question_id", questionId)
                .and(q -> q.eq("status", StatusConstants.CommentStatus.APPROVED)
                        .or()
                        .eq("user_id", userId)); // 包括自己发的所有状态的评论（只要不是被系统屏蔽的都可查到）

        // 排除被禁用或删除的评论（如果有对应状态的话，这里假设只有 approved 和 pending/rejected 可见）
        wrapper.ne("status", StatusConstants.CommentStatus.DISABLED); // 可选：排除禁用评论
        List<Comment> comments = this.list(wrapper);

        if (comments.isEmpty()) return comments;

        // 获取所有评论者的 ID
        List<Long> userIds = comments.stream()
                .map(Comment::getUserId)
                .distinct()
                .collect(Collectors.toList());

        if (userIds.size() > 0) {
            // 查询用户名
            QueryWrapper<User> userWrapper = new QueryWrapper<>();
            userWrapper.in("id", userIds).select("id", "username");
            List<User> users = userService.list(userWrapper);

            Map<Long, String> usernameMap = users.stream()
                    .collect(Collectors.toMap(User::getId, User::getUsername));

            // 填充用户名
            comments.forEach(c -> c.setUsername(usernameMap.getOrDefault(c.getUserId(), "未知用户")));
        }

        // 去重：可能因 OR 条件导致重复，虽然主键唯一不会真重复，但保险起见可按 id 去重
        return comments.stream()
                .collect(Collectors.toMap(Comment::getId, c -> c, (a, b) -> a))
                .values()
                .stream()
                .sorted((a, b) -> b.getCreatedAt().compareTo(a.getCreatedAt())) // 再确保一次排序
                .collect(Collectors.toList());
    }

    // 权限判断：是否为提问者 或 已接受任务的专家
    private boolean isNotAllowedToAccessQuestion(Long questionId, Long userId) {
        // 1. 查询问题
        Question question = questionService.getById(questionId);
        if (question == null) {
            throw new IllegalArgumentException("问题不存在");
        }

        // 2. 如果是提问者本人
        if (question.getUserId().equals(userId)) {
            return false;
        }

        // 3. 查询是否为已被分配且已接受的专家
        List<QuestionAssignment> assignments = questionAssignmentMapper.selectList(
                new QueryWrapper<QuestionAssignment>()
                        .eq("question_id", questionId)
                        .eq("expert_id", userId)
                        .eq("accepted", StatusConstants.AssignmentStatus.ACCEPTED)
        );

        return assignments.isEmpty();
    }

    @Override
    public void updateComment(Long commentId, Long userId, String newContent) {
        Comment comment = this.getById(commentId);
        if (comment == null) {
            throw new BusinessException("评论不存在");
        }

        // 权限校验：只能修改自己的评论
        if (!comment.getUserId().equals(userId)) {
            throw new BusinessException("无权修改此评论");
        }

        // 状态校验：已被禁用的评论不能修改
        if (StatusConstants.CommentStatus.DISABLED.equals(comment.getStatus())) {
            throw new BusinessException("该评论已被禁用，无法修改");
        }

        // 更新内容 & 重置状态为待审核
        comment.setContent(newContent);
        comment.setStatus(StatusConstants.CommentStatus.PENDING); // 修改后需重新审核
        comment.setUpdatedAt(LocalDateTime.now());

        boolean success = this.updateById(comment);
        if (!success) {
            throw new BusinessException("评论更新失败");
        }
    }

    @Override
    public void deleteComment(Long commentId, Long userId) {
        Comment comment = this.getById(commentId);
        if (comment == null) {
            throw new BusinessException("评论不存在");
        }

        // 只能删除自己的评论
        if (!comment.getUserId().equals(userId)) {
            throw new BusinessException("无权删除此评论");
        }

        boolean success = this.removeById(comment);
        if (!success) {
            throw new BusinessException("评论删除失败");
        }
    }

    @Override
    public void deleteCommentsForQuestion(Long questionId) {
        // 删除问题下的所有评论
        QueryWrapper<Comment> wrapper = new QueryWrapper<>();
        wrapper.eq("question_id", questionId);
        remove(wrapper);
    }
}
